package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.encrypt.EncryptUtil;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.taxdeclaration.bo.TaxDeclarationBO;
import com.engine.salary.entity.taxdeclaration.bo.TaxDeclarationDetailBO;
import com.engine.salary.entity.taxdeclaration.dto.*;
import com.engine.salary.entity.taxdeclaration.param.TaxDeclarationDetailListQueryParam;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationDetailPO;
import com.engine.salary.entity.taxdeclaration.po.TaxDeclarationPO;
import com.engine.salary.enums.salaryaccounting.EmployeeTypeEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.taxdeclaration.TaxDeclarationDetailMapper;
import com.engine.salary.service.SalaryEmployeeService;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.service.TaxDeclarationDetailService;
import com.engine.salary.service.TaxDeclarationService;
import com.engine.salary.sys.entity.vo.OrderRuleVO;
import com.engine.salary.sys.service.SalarySysConfService;
import com.engine.salary.sys.service.impl.SalarySysConfServiceImpl;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import weaver.hrm.User;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 个税申报表明细
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class TaxDeclarationDetailServiceImpl extends Service implements TaxDeclarationDetailService {

    private EncryptUtil encryptUtil = new EncryptUtil();

    private TaxDeclarationDetailMapper getTaxDeclarationDetailMapper() {
        return MapperProxyFactory.getProxy(TaxDeclarationDetailMapper.class);
    }

    private SalaryEmployeeService getSalaryEmployeeService() {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private TaxDeclarationService getTaxDeclarationService(User user) {
        return ServiceUtil.getService(TaxDeclarationServiceImpl.class, user);
    }

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return (SalaryEmployeeService) ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

    private SalarySysConfService getSalarySysConfService(User user) {
        return ServiceUtil.getService(SalarySysConfServiceImpl.class, user);
    }

    @Override
    public List<TaxDeclarationDetailPO> listByTaxDeclarationIdAndEmployeeIds(Long taxDeclarationId, Collection<Long> employeeIds) {
        if (CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }

        return getTaxDeclarationDetailMapper().listByTaxDeclarationIdAndEmployeeIds(taxDeclarationId, employeeIds);
    }

    @Override
    public PageInfo<TaxDeclarationEmployeeDTO> listPage4EmployeeIdByParam(TaxDeclarationDetailListQueryParam queryParam) {
        //排序配置
        OrderRuleVO orderRule = getSalarySysConfService(user).orderRule();
        queryParam.setOrderRule(orderRule);

//        SalaryPageUtil.start(queryParam.getCurrent(), queryParam.getPageSize());
        List<TaxDeclarationEmployeeDTO> taxDeclarationEmployeeDTOS = getTaxDeclarationDetailMapper().listPage4EmployeeId(queryParam);
        taxDeclarationEmployeeDTOS = taxDeclarationEmployeeDTOS.stream().filter(SalaryEntityUtil.distinctByKey(TaxDeclarationEmployeeDTO::getEmployeeId)).collect(Collectors.toList());

        List<TaxDeclarationEmployeeDTO> list = SalaryPageUtil.subList(queryParam.getCurrent(), queryParam.getPageSize(), taxDeclarationEmployeeDTOS);
        PageInfo<TaxDeclarationEmployeeDTO> pageInfo = new PageInfo<>(list, TaxDeclarationEmployeeDTO.class);
        pageInfo.setPageNum(queryParam.getCurrent());
        pageInfo.setPageSize(queryParam.getPageSize());
        pageInfo.setTotal(taxDeclarationEmployeeDTOS.size());
        return pageInfo;
    }

    @Override
    public PageInfo<TaxDeclarationDetailListDTO> listDtoPageByParam(TaxDeclarationDetailListQueryParam queryParam) {
        // 查询个税申报表明细的人员
        List<Long> employeeIdPage = getTaxDeclarationDetailMapper().listEmployeeId(queryParam.getTaxDeclarationId());
        PageInfo<TaxDeclarationDetailListDTO> dtoPage = new PageInfo<TaxDeclarationDetailListDTO>(TaxDeclarationDetailListDTO.class);
        dtoPage.setPageNum(queryParam.getCurrent());
        dtoPage.setPageSize(queryParam.getPageSize());
        if (null == employeeIdPage) {
            return dtoPage;
        }
        if (CollectionUtils.isNotEmpty(employeeIdPage)) {
            // 查询个税申报表明细
            List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = listByTaxDeclarationIdAndEmployeeIds(queryParam.getTaxDeclarationId(), employeeIdPage);
            // 查询人员
            List<DataCollectionEmployee> simpleEmployees = getSalaryEmployeeService().getEmployeeByIdsAll(employeeIdPage);
            // List<SimpleEmployee> simpleEmployees = hrmCommonEmployeeService.getEmployeeByIds(employeeIdPage.getRecords(), tenantKey);
            // 转换成列表dto
            TaxDeclarationBO.buildDetailListDTO(queryParam.getTaxDeclarationId(), dtoPage, taxDeclarationDetailPOS, simpleEmployees);
        }
        return dtoPage;
    }

    @Override
    public PageInfo<TaxDeclarationLaborListDTO> listDtoPageByParam4Labor(TaxDeclarationDetailListQueryParam queryParam) {

        // 查询个税申报主表
        TaxDeclarationPO taxDeclarationPO = getTaxDeclarationService(user).getById(queryParam.getTaxDeclarationId());
        // 判断是否有权限查看
        boolean canSee = getTaxDeclarationService(user).checkByAuthority(taxDeclarationPO, (long) user.getUID());
        if (!canSee) {
            throw new SalaryRunTimeException("对不起，您暂时没有权限查看");
        }
        // 查询个税申报表明细的人员
        PageInfo<TaxDeclarationEmployeeDTO> employeeIdPage = listPage4EmployeeIdByParam(queryParam);
        PageInfo<TaxDeclarationLaborListDTO> dtoPage = new PageInfo<>(TaxDeclarationLaborListDTO.class);
        dtoPage.setPageSize(employeeIdPage.getPageSize());
        dtoPage.setPageNum(employeeIdPage.getPageNum());
        dtoPage.setTotal(employeeIdPage.getTotal());
        List list = employeeIdPage.getList();
        if (CollectionUtils.isNotEmpty(list)) {
            // 转换成列表dto
            List<TaxDeclarationLaborListDTO> taxDeclarationLaborListDTOS = listDto4Labor(queryParam.getTaxDeclarationId(), list);
            dtoPage.setList(taxDeclarationLaborListDTOS);
        }
        return dtoPage;
    }

    @Override
    public PageInfo<TaxDeclarationAnnualListDTO> listDtoPageByParam4Annual(TaxDeclarationDetailListQueryParam queryParam) {
        // 查询个税申报主表
        TaxDeclarationPO taxDeclarationPO = getTaxDeclarationService(user).getById(queryParam.getTaxDeclarationId());
        // 判断是否有权限查看
        boolean canSee = getTaxDeclarationService(user).checkByAuthority(taxDeclarationPO, (long) user.getUID());
        if (!canSee) {
            throw new SalaryRunTimeException("对不起，您暂时没有权限查看");
        }
        // 查询个税申报表明细的人员
        PageInfo<TaxDeclarationEmployeeDTO> employeeIdPage = listPage4EmployeeIdByParam(queryParam);
        PageInfo<TaxDeclarationAnnualListDTO> dtoPage = new PageInfo<>(TaxDeclarationAnnualListDTO.class);
        dtoPage.setPageSize(employeeIdPage.getPageSize());
        dtoPage.setPageNum(employeeIdPage.getPageNum());
        dtoPage.setTotal(employeeIdPage.getTotal());
        List list = employeeIdPage.getList();
        if (CollectionUtils.isNotEmpty(list)) {
            // 转换成列表dto
            List<TaxDeclarationAnnualListDTO> taxDeclarationLaborListDTOS = listDto4Annual(queryParam.getTaxDeclarationId(), list);
            dtoPage.setList(taxDeclarationLaborListDTOS);
        }
        return dtoPage;
    }

    @Override
    public List<TaxDeclarationLaborListDTO> listDto4Labor(Long taxDeclarationId, List<TaxDeclarationEmployeeDTO> taxDeclarationEmployees) {
        long employeeId = (long) user.getUID();
        // 查询个税申报主表
        TaxDeclarationPO taxDeclarationPO = getTaxDeclarationService(user).getById(taxDeclarationId);
        // 判断是否有权限查看
        boolean canSee = getTaxDeclarationService(user).checkByAuthority(taxDeclarationPO, employeeId);
        if (!canSee) {
            throw new SalaryRunTimeException("对不起，您暂时没有权限查看");
        }
        // 查询个税申报表明细
        List<Long> employeeIds = taxDeclarationEmployees.stream().map(TaxDeclarationEmployeeDTO::getEmployeeId).collect(Collectors.toList());
        List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = listByTaxDeclarationIdAndEmployeeIds(taxDeclarationId, employeeIds);
        // 查询人员信息
        List<DataCollectionEmployee> simpleEmployees = getSalaryEmployeeService().getEmployeeByIdsAll(employeeIds);
        // 转换成列表dto
        return TaxDeclarationDetailBO.convert2ListDTO4Labor(taxDeclarationDetailPOS, taxDeclarationEmployees, simpleEmployees);
    }

    public List<TaxDeclarationAnnualListDTO> listDto4Annual(Long taxDeclarationId, List<TaxDeclarationEmployeeDTO> taxDeclarationEmployees) {
        long employeeId = (long) user.getUID();
        // 查询个税申报主表
        TaxDeclarationPO taxDeclarationPO = getTaxDeclarationService(user).getById(taxDeclarationId);
        // 判断是否有权限查看
        boolean canSee = getTaxDeclarationService(user).checkByAuthority(taxDeclarationPO, employeeId);
        if (!canSee) {
            throw new SalaryRunTimeException("对不起，您暂时没有权限查看");
        }
        // 查询个税申报表明细
        List<Long> employeeIds = taxDeclarationEmployees.stream().map(TaxDeclarationEmployeeDTO::getEmployeeId).collect(Collectors.toList());
        List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = listByTaxDeclarationIdAndEmployeeIds(taxDeclarationId, employeeIds);
        // 查询人员信息
        List<DataCollectionEmployee> simpleEmployees = getSalaryEmployeeService().getEmployeeByIdsAll(employeeIds);
        // 转换成列表dto
        return TaxDeclarationDetailBO.convert2ListDTO4Annual(taxDeclarationDetailPOS, taxDeclarationEmployees, simpleEmployees);
    }


    @Override
    public PageInfo<TaxDeclarationWageListDTO> listDtoPageByParam4Wage(TaxDeclarationDetailListQueryParam queryParam) {

        // 查询个税申报表明细的人员
        PageInfo<TaxDeclarationEmployeeDTO> employeeIdPage = listPage4EmployeeIdByParam(queryParam);

        PageInfo<TaxDeclarationWageListDTO> dtoPage = SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(), TaxDeclarationWageListDTO.class);
        dtoPage.setTotal(employeeIdPage.getTotal());
        if (CollectionUtils.isNotEmpty(employeeIdPage.getList())) {
            List<TaxDeclarationEmployeeDTO> list = employeeIdPage.getList();
            // 查询个税申报表明细
            Set<Long> employeeIds = SalaryEntityUtil.properties(list, TaxDeclarationEmployeeDTO::getEmployeeId);
            List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = listByTaxDeclarationIdAndEmployeeIds(queryParam.getTaxDeclarationId(),
                    employeeIds);
            encryptUtil.decryptList(taxDeclarationDetailPOS, TaxDeclarationDetailPO.class);
            // 查询人员信息
            List<Long> simpleEmployeeIds = list.stream()
                    .filter(taxDeclarationEmployeeDTO -> Objects.equals(taxDeclarationEmployeeDTO.getEmployeeType(), EmployeeTypeEnum.ORGANIZATION.getValue()))
                    .map(TaxDeclarationEmployeeDTO::getEmployeeId)
                    .collect(Collectors.toList());
            List<DataCollectionEmployee> simpleEmployees = getSalaryEmployeeService(user).getEmployeeByIds(simpleEmployeeIds);
            List<TaxDeclarationWageListDTO> taxDeclarationWageListDTOS = TaxDeclarationDetailBO.convert2ListDTO4Wage(taxDeclarationDetailPOS,
                    employeeIdPage.getList(), simpleEmployees);
            dtoPage.setList(taxDeclarationWageListDTOS);
        }
        return dtoPage;

    }

    @Override
    public void batchSave(Collection<TaxDeclarationDetailPO> taxDeclarationDetailPOS) {
        if (CollectionUtils.isNotEmpty(taxDeclarationDetailPOS)) {
            taxDeclarationDetailPOS = encryptUtil.encryptList(new ArrayList<>(taxDeclarationDetailPOS), TaxDeclarationDetailPO.class);
            List<List<TaxDeclarationDetailPO>> partition = Lists.partition((List) taxDeclarationDetailPOS, 100);
            partition.forEach(getTaxDeclarationDetailMapper()::batchInsert);
        }
    }

    public List<TaxDeclarationDetailPO> listByTaxDeclarationIdAndEmployeeIds(Long taxDeclarationId, List<Long> employeeIds) {
        if (CollectionUtils.isEmpty(employeeIds)) {
            return Collections.emptyList();
        }

        List<TaxDeclarationDetailPO> taxDeclarationDetailPOS = getTaxDeclarationDetailMapper().listByTaxDeclarationIdAndEmployeeIds(taxDeclarationId, employeeIds);
        return encryptUtil.decryptList(taxDeclarationDetailPOS, TaxDeclarationDetailPO.class);
    }

    @Override
    public void deleteByTaxDeclarationIds(Collection<Long> taxDeclarationIds) {
        getTaxDeclarationDetailMapper().deleteByTaxDeclarationIds(taxDeclarationIds);
    }
}
